package com.kmxd.ams.infra.seal.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.kmxd.ams.client.system.ISysConfigSvc;
import com.kmxd.ams.core.common.constant.ConfigConst;
import com.kmxd.ams.core.oss.template.OssTemplate;
import com.kmxd.ams.infra.archive.entity.ArchiveSeal;
import com.kmxd.ams.infra.arrange.entity.Document;
import com.kmxd.ams.infra.seal.service.ISealSvc;
import com.kmxd.ams.infra.seal.setting.NumberSetting;
import com.kmxd.ams.infra.seal.setting.SealSetting;
import com.kmxd.ams.infra.seal.utils.ArchPdfSeal;
import com.yh.scofd.agent.HTTPAgent;
import com.yh.scofd.agent.wrapper.model.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.imageio.ImageIO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * ofd档号章实现
 *
 * @author ZuoLG
 */
@Slf4j
@Service("ofdSeal")
@RequiredArgsConstructor
public class OfdSealSvcImpl implements ISealSvc {

  private final ISysConfigSvc sysConfigSvc;
  private final OssTemplate ossTemplate;

  /**
   * 获取地址
   *
   * @return
   */
  public String getUrl() {
    String archSeal = sysConfigSvc.getConfigContentByKey(ConfigConst.OSS_TRANSFER);
    if (StrUtil.isNotBlank(archSeal) && JSONUtil.isTypeJSON(archSeal)) {
      JSONObject sealSetting = JSONUtil.parseObj(archSeal);
      return sealSetting.get("transferURL", null);
    }
    return null;
  }

  /**
   * 获取表格配置信息 { "sealSetting":
   * {"sealX":"10","sealY":"10","sealWidth":"300","sealHeight":"30","sealLineWidth":"1","sealFont":"仿宋","sealFontSize":"12"}
   *
   * @param archSeal
   * @return
   */
  private SealSetting getSealSetting(ArchiveSeal archSeal) {
    SealSetting table = new SealSetting().setX(10).setY(10).setWidth(80 * 2).setHeight(26 * 2);
    if (StrUtil.isNotBlank(archSeal.getSealSetting())
        && JSONUtil.isTypeJSON(archSeal.getSealSetting())) {
      JSONObject sealSetting = JSONUtil.parseObj(archSeal.getSealSetting());
      table.setPositionX(sealSetting.getInt("sealX", 105));
      table.setPositionY(sealSetting.getInt("sealY", 5));
      table.setWidth(sealSetting.getInt("sealWidth", 200));
      table.setHeight(sealSetting.getInt("sealHeight", 60));
      table.setLineWidth(sealSetting.getInt("sealLineWidth", 1));
      table.setRowHeight(sealSetting.getInt("sealRowHeight", 30));

      String fontColorName = sealSetting.getStr("sealFontColor", "#FF0000");
      Color fontColor = Color.decode(fontColorName);
      table.setFontColor(fontColor);

      String lineColorName = sealSetting.getStr("sealLineColor", "#FF0000");
      Color lineColor = Color.decode(lineColorName);
      table.setLineColor(lineColor);

      String fontName = sealSetting.getStr("sealFont", "宋体");
      int fontSize = sealSetting.getInt("sealFontSize", 12);
      Font font = new Font(fontName, Font.PLAIN, fontSize);
      table.setHeaderFont(font);
      table.setCellFont(font);
    }

    return table;
  }

  /**
   * 获取编号配置信息 {"numX":"10","numY":"10","numHeaderFont":"宋体","numFontSize":"12"}
   *
   * @param archSeal
   * @return
   */
  private NumberSetting getNumObj(ArchiveSeal archSeal) {
    NumberSetting numSetting = new NumberSetting();
    if (StrUtil.isNotBlank(archSeal.getNumSetting())
        && JSONUtil.isTypeJSON(archSeal.getNumSetting())) {
      JSONObject sealSetting = JSONUtil.parseObj(archSeal.getNumSetting());
      numSetting.setPositionX(sealSetting.getInt("numX", 90));
      numSetting.setPositionY(sealSetting.getInt("numY", 135));
      numSetting.setFontName(sealSetting.getStr("numHeaderFont", "宋体"));
      numSetting.setFontSize(sealSetting.getInt("numFontSize", 10));
      numSetting.setNumIndex(sealSetting.getInt("numIndex", 1));
    }
    return numSetting;
  }

  /**
   * 获取文件名称
   * @param filePath
   * @param title
   * @return
   */
  private String getOutFileName(String filePath, String title) {
    String basePath = ossTemplate.getSystemTempPath();
    FileUtil.mkdir(basePath);
    String yearName = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_MS_PATTERN);
    String fileName =
        basePath + StrUtil.format("{}_{}.{}", title, yearName, FileUtil.getSuffix(filePath));
    return fileName;
  }

  @Override
  public File genSeal(ArchiveSeal archSeal, String fileTitle, String filePath, Document doc) {
    try {
      final HTTPAgent agent = new HTTPAgent(getUrl());
      File ofdFile = null;
      NumberSetting numSetting = getNumObj(archSeal);
      if (ObjectUtil.equals(archSeal.getEnableNum(), 1)) {
        ofdFile = genNum(archSeal, fileTitle, numSetting, filePath);
      } else {
        ofdFile = FileUtil.file(filePath);
      }
      SealSetting table = getSealSetting(archSeal);
      if (ObjectUtil.notEqual(archSeal.getEnableSeal(), 1)) {
        return ofdFile;
      }

      File outFile = FileUtil.file(getOutFileName(filePath, fileTitle));
      // 需要添加水印的页面
      int[] pages = {1};
      MarkPosition mk =
          new MarkPosition(
              table.getPositionX(),
              table.getPositionY(),
              table.getWidth() / 2,
              table.getHeight() / 2,
              pages);
      BufferedOutputStream out = FileUtil.getOutputStream(outFile);
      // 获取档号章样式
      InputStream inputStream = getSealStyle1(table, doc);
      ImageInfo imageInfo = new ImageInfo("png", inputStream);
      agent.addImageMark(ofdFile, out, imageInfo, mk);
      IoUtil.close(out);
      IoUtil.close(inputStream);
      agent.close();
      return outFile;
    } catch (Exception ex) {
      ex.printStackTrace();
      log.info("生成档号章样式异常！");
    }
    return null;
  }

  /**
   * 生成页码文件
   *
   * @param archSeal
   * @param numSetting
   * @param filePath
   * @return
   */
  private File genNum(
      ArchiveSeal archSeal, String fileTitle, NumberSetting numSetting, String filePath) {
    File ofdFile = FileUtil.file(filePath);
    try {
      final HTTPAgent agent = new HTTPAgent(getUrl());
      File outFile = FileUtil.file(getOutFileName(filePath, fileTitle));
      BufferedOutputStream out = FileUtil.getOutputStream(outFile);
      // 处理文字水印 start
      int page = agent.getPageCount(ofdFile);
      List<TextWaterMarkInfo> numMarks = addTextMarks(page, numSetting);
      agent.addTextMarkMultiLine(ofdFile, out, numMarks);
      // 处理文字水印 end
      IoUtil.close(out);
      agent.close();
      return outFile;
    } catch (Exception ex) {
      ex.printStackTrace();
      log.info("添加ofd文件数字编号异常！");
    }
    return ofdFile;
  }

  /**
   * 获取添加的页面
   *
   * @param page
   * @param numSetting
   * @return
   */
  public static List<TextWaterMarkInfo> addTextMarks(int page, NumberSetting numSetting) {
    List<TextWaterMarkInfo> numMarks = new ArrayList<>();
    // 获取ofd文件页数
    for (int i = 1; i <= page; i++) {
      MarkPosition position =
          new MarkPosition(
              numSetting.getPositionX(), numSetting.getPositionY(), 0, 0, new int[] {i});
      int num = i - 1 + numSetting.getNumIndex();
      TextInfo textInfo =
          new TextInfo(
              String.valueOf(num), numSetting.getFontName(), numSetting.getFontSize(), "#000000");
      numMarks.add(new TextWaterMarkInfo(textInfo, position));
    }
    return numMarks;
  }

  /**
   * 获取档号章样式
   *
   * @param table
   * @param doc
   * @return
   * @throws Exception
   */
  public static InputStream getSealStyle1(SealSetting table, Document doc) throws Exception {
    String fondsCode = ObjectUtil.isNotEmpty(doc.getFondsCode()) ? doc.getFondsCode() : "";
    String year = ObjectUtil.isNotEmpty(doc.getYear()) ? String.valueOf(doc.getYear()) : "";
    String docSequence =
        ObjectUtil.isNotEmpty(doc.getDocSequence()) ? String.valueOf(doc.getDocSequence()) : "";
    String orgFunction =
        ObjectUtil.isNotEmpty(doc.getClassfyName()) ? String.valueOf(doc.getClassfyName()) : "";
    String retentionPeriod =
        ObjectUtil.isNotEmpty(doc.getRetentionPeriod())
            ? String.valueOf(doc.getRetentionPeriod())
            : "";
    String pageNum =
        ObjectUtil.isNotEmpty(doc.getPageNum()) ? String.valueOf(doc.getPageNum()) : "";

    List<ArchPdfSeal> headCells = new ArrayList<>();
    headCells.add(
        new ArchPdfSeal(1, 1, table.getWidth() / 3, 1).setTextAlign(true).setContent(fondsCode));
    headCells.add(
        new ArchPdfSeal(1, 2, table.getWidth() / 3, 1).setTextAlign(true).setContent(year));
    headCells.add(
        new ArchPdfSeal(1, 3, table.getWidth() / 3, 1).setTextAlign(true).setContent(docSequence));

    table.setHeadCells(headCells);
    java.util.List<java.util.List<String>> tableRowContents = new ArrayList<>();
    java.util.List<String> row1 =
        Stream.of(orgFunction, retentionPeriod, pageNum).collect(Collectors.toList());
    tableRowContents.add(row1);
    BufferedImage bufferedImage = ArchPdfSeal.getArchSeal(table, tableRowContents);
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    ImageIO.write(bufferedImage, "png", os);
    IoUtil.close(os);
    InputStream inputStream = new ByteArrayInputStream(os.toByteArray());
    IoUtil.close(inputStream);
    return inputStream;
  }
}
